package com.example.export_data.service;

import com.alibaba.fastjson.JSONObject;
import com.example.WebApplication;
import com.example.export_data.bean.ApiResult;
import com.example.export_data.bean.User;
import com.example.export_data.bean.UserDetail;
import com.example.export_data.bean.UserExpand;
import com.example.export_data.mapper.UserDetailJpa;
import com.example.export_data.mapper.UserExpandJpa;
import com.example.export_data.mapper.UserJpa;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = WebApplication.class)
@Slf4j
public class ExportUserService {
    @Resource
    private UserJpa userJpa;

    private UserDetailJpa userDetailJpa;

    @Resource
    private UserExpandJpa userExpandJpa;

    private String token = "ee2ea036-b792-45e1-8061-a5abc1e0617f";

    private RestTemplate restTemplate = new RestTemplate();

    private List<User> userList = new ArrayList();

    BlockingQueue<Long> queue = new LinkedBlockingQueue<>();

    private List<UserExpand> userExpandList = new ArrayList();

    private List<UserDetail> userDetailList = new ArrayList();

    AtomicInteger num = new AtomicInteger(0);

    @Test
    public void getUserInfoList() {
        Long start = new Date().getTime();
//        getUserInfoList(0l);
        /*List list = new ArrayList();
        list.add(2115067772);*/
//        getUserDetail(list);
        getUserExtend(2246068081L);
       /* if (userExtendList.size() > 0) {
            userExpandJpa.saveAll(userExtendList);
            log.info("保存了{}数据", userExtendList.size());
        }*/
        log.info("花费了{}秒", (new Date().getTime() - start) / 1000);
    }

    /**
     * @param cursor 游标
     */
    public void getUserInfoList(Long cursor) {
        String url = "https://dopen.weimob.com/api/1_0/mc/member/getMemberList?accesstoken=" + token;
        TreeMap<String, Object> params = new TreeMap();
        log.info("查询数据参数 cursor = {}", cursor);
        params.put("cursor", cursor);
        params.put("size", 100);//滚动数量，最大100
        Long begin = new Date().getTime();
        ApiResult<Map> apiResult = restTemplate.postForObject(url, params, ApiResult.class);
        log.info("-------- http request 花费了{}毫秒", (new Date().getTime() - begin));

        log.info(apiResult.toString());
        List items = (List) apiResult.getData().get("items");
        if (items == null || items.size() == 0) {
            return;
        }
        userList.clear();
        List<Long> wids = new ArrayList();
        for (Object object : items) {
            User user = JSONObject.parseObject(JSONObject.toJSON(object).toString(), User.class);
            userList.add(user);
            //user detail
//            wids.add(user.getWid());
            //user extend
//            getUserExtend(user.getWid());
        }
        Long start = new Date().getTime();
        List<User> users = userJpa.saveAll(userList);
        log.info("            -------- insert mysql 花费了{}毫秒", (new Date().getTime() - start));

//        getUserDetail(wids);

        cursor = ((Integer) apiResult.getData().get("cursor")).longValue();
        getUserInfoList(cursor);

    }

    ThreadPoolExecutor executorService = new ThreadPoolExecutor(0, 100,
            0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(1000),
            new ThreadFactoryBuilder().setNameFormat("task-pool-%d").build(),
            new ThreadPoolExecutor.CallerRunsPolicy());

    //    ExecutorService executorService = Executors.newFixedThreadPool(50);
    @Test
    public void loadUserExpand() {
        try {
            readUserInfo();
        } catch (Exception e) {
            log.error("", e);
        }
    }

    public void readUserInfo() {
        CountDownLatch latch = new CountDownLatch(1);
        Long start = System.currentTimeMillis();
        Thread thread1 = new Thread(() -> {
            int page = 0;
            while (getUserInfo(page++).size() > 0) {
//            if(getUserInfo(page++).size() > 0) {
                log.info("正在查询第{}页", page);
            }
        }
        );
        thread1.start();

        new Thread(() -> {
            boolean flag = true;
            while (flag) {
                Long wid = queue.poll();
                if (!thread1.isAlive() && wid == null) {
                    if (!executorService.isShutdown()) {
                        executorService.shutdown();
                    }
                }
                if (wid != null) {
                    executorService.submit(() ->
                            {
                                log.info("wid -- = {}", wid);
                                log.info("thread1 = {},getActiveCount ={}, 已处理{}, queue size = {}",
                                        thread1.isAlive(), (executorService).getActiveCount(),
                                        num.getAndIncrement(), queue.size());
                                //业务处理
                                getUserExtend(wid);
                            }
                    );
                }
                if (executorService.isTerminated()) {
                    flag = false;
                    latch.countDown();
                }
            }
        }).start();

        try {
            latch.await();
            log.info("执行完了。。。。。");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        List<UserExpand> list = new ArrayList<>();
        for (UserExpand userExpand : userExtendList) {
            list.add(userExpand);
            if (list.size() >= 300) {
                long start1 = System.currentTimeMillis();
                userExpandJpa.saveAll(list);
                log.info("保存了{}数据,花费了 {} 毫秒", list.size(), System.currentTimeMillis() - start1);
                list.clear();
            }
        }
        if (list.size() > 0) {
            long start1 = System.currentTimeMillis();
            userExpandJpa.saveAll(list);
            log.info("保存了{}数据,花费了 {} 毫秒", list.size(), System.currentTimeMillis() - start1);
        }
        log.info("一共花费了{}秒", (System.currentTimeMillis() - start) / 1000);

    }

    public List<User> getUserInfo(int page) {
        int size = 100;
        Page<User> users = userJpa.findAll(PageRequest.of(page, size, Sort.by("wid")));
        if (users.getSize() > 0) {
            List<Long> wids = users.stream().map(User::getWid).collect(Collectors.toList());
            queue.addAll(wids);
            log.info("----------------- add wids {}个,queue size = {} ------------------", wids.size(), queue.size());
            //getUserDetail(wids);
            /*for (User user : users) {
                getUserExtend(user.getWid());
            }*/

        }
        return users.getContent();
    }

    public void getUserDetail(List wids) {
        List<UserDetail> list = new ArrayList<>();
        String url = "https://dopen.weimob.com/api/1_0/mc/member/getMemberListByWids?accesstoken=" + token;
        TreeMap<String, Object> params = new TreeMap();
        params.put("widList", wids);//wid集合,支持最多100个
        params.put("isNeedExtInfo", true);//是否需要查询会员的扩展信息 默认false
        params.put("isNeedTagsInfo", true);//是否需要查询包括标签信息 默认false
        ApiResult<Map> apiResult = restTemplate.postForObject(url, params, ApiResult.class);
        log.info(apiResult.toString());
        List items = (List) apiResult.getData().get("items");
        for (Object object : items) {
            UserDetail userDetail = JSONObject.parseObject(JSONObject.toJSON(object).toString(), UserDetail.class);
            list.add(userDetail);
        }
//        userDetailJpa.saveAll(list);

    }

    List<UserExpand> userExtendList = new CopyOnWriteArrayList<>();

    public void getUserExtend(Long wid) {
        String url = "https://dopen.weimob.com/api/1_0/uc/user/getUserInfo?accesstoken=" + token;
        TreeMap<String, Object> params = new TreeMap();
        params.put("wid", wid);
        Date start = new Date();
        ApiResult<Map> apiResult = restTemplate.postForObject(url, params, ApiResult.class);
        log.info("already request http, cost = {}", (new Date().getTime() - start.getTime()));
        log.info(apiResult.toString());
        Object errcode = apiResult.getCode().get("errcode");
        if (!"0".equals(errcode.toString())) {
            log.error("", new RuntimeException(apiResult.toString()));
        }
        Long superWid = Long.parseLong(apiResult.getData().get("superWid").toString());
        if (superWid != wid.longValue()) {
            delUser(wid);
            return;
        }
        Long pid = (Long) apiResult.getData().get("pid");
        List<Map> sourceObjectList = (List) apiResult.getData().get("sourceObjectList");
        for (Map object : sourceObjectList) {
            //渠道类型： 0 微信公众号 ，1 微信小程序 ，3 微盟openid（ 当商户的公众号没有网页授权能力时由微盟公众号代授权）， 4 手机号 phone
            Object source1 = object.get("source");
            if (!"1".equals(source1.toString())) {
                continue;//支取小程序信息
            }
            Map sourceData = (Map) object.get("sourceData");
            UserExpand userExpand = new UserExpand();
            if (sourceData != null) {
                userExpand = JSONObject.parseObject(JSONObject.toJSON(sourceData).toString(), UserExpand.class);
                userExpand.setSource((Integer) object.get("soure"));
                userExpand.setSourceAppid((String) object.get("soureAppid"));
                userExpand.setSourceOpenid((String) object.get("soureOpenid"));
                userExpand.setSuperWid(superWid.longValue());
                userExpand.setPid(pid);
                userExtendList.add(userExpand);
            } else {
                userExpand.setSource((Integer) object.get("soure"));
                userExpand.setSourceAppid((String) object.get("soureAppid"));
                userExpand.setSourceOpenid((String) object.get("soureOpenid"));
                userExpand.setSuperWid(superWid.longValue());
                userExpand.setPid(pid);
                userExtendList.add(userExpand);
            }
        }

    }

    private void delUser(Long wid) {
        userJpa.delUser(wid);
    }

    @Test
    public void test1() {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5,
                5L, TimeUnit.MINUTES,
                new ArrayBlockingQueue<>(10), // 队列不要太长，这样才能阻塞住 for 循环
                new ThreadFactoryBuilder().setNameFormat("task-pool-%d").build(),
                new ThreadPoolExecutor.CallerRunsPolicy());
        AtomicInteger num = new AtomicInteger(0);
        for (int i = 0; i < 90001; i++) {
            executor.submit(new Runnable() {
                @Override
                public void run() {
                    log.info("{}", num.getAndIncrement());
                    // 业务发请求
                }
            });
        }
    }

    BlockingQueue<String> openIdQueue = new LinkedBlockingQueue<>();

    @Test
    public void getUserUni() throws InterruptedException {
        long start = System.currentTimeMillis();
        List<String> oaOpenUsers = userJpa.getOaOpenUsers();
        openIdQueue.addAll(oaOpenUsers);
        for (String oaOpenid : oaOpenUsers) {
            executorService.submit(() ->
                    {
                        //业务处理
                        String userUni = getOaUserUni(oaOpenid);
                        if (StringUtils.isNotBlank(userUni)) {
                            userJpa.updateUserByOaOpenId(userUni, oaOpenid);
                        }
                       /* String sql = "update ums_imall_user set unionid = {} where oa_openid = {};";
                        log.error(sql,userUni,oaOpenid);*/
                    }
            );

        }

        executorService.shutdown();
        if (executorService.awaitTermination(1, TimeUnit.SECONDS)) {
            log.info("执行完了");
        }
//        getOaUserUni("oZdZbwKeJc9eLdWgTF1X4BG9sAoI");
        log.info("花费了{}秒", (System.currentTimeMillis() - start) / 1000);
    }
    @Test
    public void testOaUserUni(){
        getOaUserUni("oZdZbwKHfe6lpTb6weOHpbM1OxxI");
    }
    @Deprecated
    public String getOaUserUni(String openid) {
//        String url = "http://manager.test.youpindayaofang.com:12345/dapi/open/wxaa/getInfo/ddypfwh?openid=" + openid;
        String url = "https://api.youpindayaofang.com/open/wxaa/getInfo/ddypfwh?openid=" + openid;
        JSONObject result = restTemplate.getForObject(url, JSONObject.class);
        log.info("result = {}", result);
        return result.getString("unionid");
    }

    @Test
    public void generateInviteCode() {
        String uinonId = "okm0O47jyXaOl1fA614SAon9TxEo";
        long time = System.currentTimeMillis();
        System.out.println(time);
        String md532 = MD5Util.md5Hex("miniApi:login:token" + time + "-" + uinonId);
        System.out.println(md532);
//        184957dbdd5fade9bd160db392c9c6be
        System.out.println(md532.substring(0, 16));

        uinonId = "o4AtxwnsdsdTkLJ5o5jll-CJ5Q1g";
        time = System.currentTimeMillis();
        System.out.println(time);
        md532 = MD5Util.md5Hex("miniApi:login:token" + time + "-" + uinonId);
        System.out.println(md532);
//        184957dbdd5fade9bd160db392c9c6be
        System.out.println(md532.substring(0, 16));
    }

    @Test
    public void generate() {
        try {
            int i = 0;
            int b = 4 / i;
        } catch (Exception e) {
            log.error("", e);
        }

    }
}
